"use strict";
// 菜单
let EMenu = function (selector, options) {
    // 目标元素
    let the = this;

    // 查找对象
    let $element = $(selector);
    let element = $element[0];
    let $body = $('body');
    let ps = null;
    if (!$element.length) {
        return;
    }

    // 默认设置
    let defaultOptions = {
        accordion: {
            slideSpeed: 200, // 子菜单打开速度
            autoScroll: false, // 自动滚动到合适位置
            autoScrollSpeed: 1200,
            expandAll: true // 允许打开多个子菜单
        }
    };
    // 私有方法
    let Plugin = {
        construct: function (options) {
            if (EUtil.data($element).has('menu')) {
                // 如果已经初始化，直接从缓存获取对象
                the = EUtil.data($element).get('menu');
            } else {
                // 初始化
                Plugin.init(options);
                // 重置
                Plugin.reset();
                // 绑定事件
                Plugin.build();
                EUtil.data($element).set('menu', the);
            }
            return the;
        },

        /**
         * 初始化
         *
         * @param options {object} options
         */
        init: function (options) {
            // 事件
            the.events = [];

            // handlers
            the.eventHandlers = {};

            // 合并默认选项&传入option
            the.options = $.extend(true, {}, defaultOptions, options);

            the.uid = EUtil.getUniqueID();
        },
        /**
         * 更改option
         *
         * @param options {object} options
         */
        update: function (options) {
            // 事件
            the.events = [];

            // handlers
            the.eventHandlers = {};

            // 合并默认选项&传入option
            the.options = $.extend(true, {}, defaultOptions, options);

            // 重置
            Plugin.reset();
            // 绑定事件
            Plugin.build();
        },
        /**
         * 重新初始化
         */
        reload: function () {
            // 重置
            Plugin.reset();
            // 绑定事件
            Plugin.build();
        },

        /**
         * 绑定事件
         */
        build: function () {
            the.eventHandlers['event_1'] = $element.on('click', '.e-menu-toggle', Plugin.handleSubmenuAccordion);
            the.eventHandlers['event_2'] = $element.on('click', '.e-menu-item:not(.e-menu-item--submenu) > .e-menu-link:not(.e-menu-toggle):not(.e-menu-link--toggle-skip)', Plugin.handleLinkClick);

            if (the.options.scroll && the.options.scroll.height) {
                Plugin.scrollInit();
            }
        },
        /**
         * 重置
         */
        reset: function () {

        },
        /**
         * 初始化滚动条
         */
        scrollInit: function () {
            if (the.options.scroll && the.options.scroll.height) {
                EUtil.scrollDestroy(element);
                EUtil.scrollInit(element, {
                    disableForMobile: true,
                    resetHeightOnDestroy: true,
                    handleWindowResize: true,
                    height: the.options.scroll.height,
                    rememberPosition: the.options.scroll.rememberPosition
                });
            } else {
                EUtil.scrollDestroy(element);
            }
        },
        /**
         * 更新菜单滚动条
         */
        scrollerUpdate: function () {
            if (the.options.scroll && the.options.scroll.height) {
                EUtil.scrollerUpdate(element);
            } else {
                EUtil.scrollDestroy(element);
            }
        },

        /**
         * 滚动到顶部
         */
        scrollerTop: function () {
            if (the.options.scroll && the.options.scroll.height) {
                EUtil.scrollTo(element, 0);
            }
        },
        scrollTo: function($item, speed){
            EUtil.scrollTo(element, $item.offset().top - $element.offset().top, speed);
        },
        /**
         * 点击菜单链接
         */
        handleLinkClick: function (e) {
            e.preventDefault();
            Plugin.eventTrigger('linkClick', this);
        },
        handleSubmenuAccordion: function (e, ele) {
            let $item = $(ele ? ele : this);

            let $li = $($item.closest('.e-menu-item'));
            let $subMenu = $li.children('.e-menu-submenu, e-menu-inner');

            if ($li.hasClass('e-menu-item--open-always')) {
                return;
            }

            if ($li.length && $subMenu.length) {
                e.preventDefault();
                let speed = the.options.accordion.slideSpeed;

                if (!$li.hasClass('e-menu-item--open')) {
                    // 未打开
                    if (!the.options.accordion.expandMultiple) {
                        // 如果不支持打开多个
                        let $subNav = $item.closest('.e-menu-nav, .e-menu-subnav');
                        let $closables = $subNav.children('.e-menu-item.e-menu-item--open.e-menu-item--submenu:not(.e-menu-item--expanded):not(.e-menu-item--open-always)');
                        if ($subNav.length && $closables.length) {
                            let $el = $($closables[0]);
                            $closables.each(function (index, el) {
                                let $subMenu = $el.children('.e-menu-submenu');
                                if ($subMenu.length) {
                                    $subMenu.slideUp(speed, function () {
                                        EUtil.scrollUpdate(element);
                                    });

                                    $el.removeClass('e-menu-item--open');
                                }
                            });
                        }
                    }
                    // 展开对应的子菜单
                    Plugin.eventTrigger('submenuToggle', $subMenu);
                    $subMenu.slideDown(speed, function () {
                        Plugin.scrollTo($item, speed);
                    });
                    $li.addClass('e-menu-item--open');
                } else {
                    Plugin.eventTrigger('submenuToggle', $subMenu);
                    $subMenu.slideUp(speed, function () {
                        Plugin.scrollTo($item, speed);
                    });
                    $li.removeClass('e-menu-item--open');
                }
            }
        },

        /**
         * 触发事件
         *
         * @param name {string} 事件名称
         * @param args {object} 参数
         */
        eventTrigger: function (name, args) {
            for (let i = 0; i < the.events.length; i++) {
                let event = the.events[i];
                if (event.name === name) {
                    if (event.one) {
                        // 一次性事件
                        if (!event.fired) {
                            // 设置事件属性为已触发，下次不执行
                            the.events[i].fired = true;
                            event.handler.call(this, the, args);
                        }
                    } else {
                        event.handler.call(this, the, args);
                    }
                }
            }
        },

        /**
         * 添加事件
         *
         * @param name {string} 事件名称
         * @param handler {function} 回调
         * @param one {boolean} 是否一次性
         */
        addEvent: function (name, handler, one) {
            the.events.push({
                name: name,
                handler: handler,
                one: one,
                fired: false
            });
        },
        /**
         * 移除事件
         *
         * @param name {string} 事件名称
         */
        removeEvent: function (name) {
            if (the.events[name]) {
                delete the.events[name];
            }
        }
    };


    // 公开方法
    /**
     * 设置默认option
     *
     * @param options {object} 选项
     */
    the.setDefaults = function (options) {
        defaultOptions = options;
    };


    /**
     * 绑定事件
     *
     * @param name {string} 事件名称
     * @param handler {function} 回调
     * @returns {*|void}
     */
    the.on = function (name, handler) {
        return Plugin.addEvent(name, handler);
    };
    /**
     * 绑定一次性事件
     *
     * @param name {string} 事件名称
     * @param handler {function} 回调
     * @returns {*|void}
     */
    the.one = function (name, handler) {
        return Plugin.addEvent(name, handler, true);
    };

    Plugin.construct.apply(the, [options]);
    return the;
};